home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / shells / rc-1.000 / rc-1 / rc-1.5-linux / footobar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-07  |  8.6 KB  |  338 lines

  1. /*
  2.    footobar.c: a collection of functions to convert internal representations of
  3.    variables and functions to external representations, and vice versa
  4. */
  5.  
  6. #include "rc.h"
  7.  
  8. /* protect an exported name from brain-dead shells */
  9.  
  10. #ifdef PROTECT_ENV
  11. static bool Fconv(Format *f, int ignore) {
  12.     unsigned const char *s = va_arg(f->args, unsigned const char *);
  13.     int c;
  14.  
  15.     while ((c = *s++) != '\0')
  16.         if (dnw[c] || c == '*' || (c == '_' && *s == '_'))
  17.             fmtprint(f, "__%02x", c);
  18.         else
  19.             fmtputc(f, c);
  20.     return FALSE;
  21. }
  22. #endif
  23.  
  24. /* convert a redirection to a printable form */
  25.  
  26. static bool Dconv(Format *f, int ignore) {
  27.     const char *name = "?";
  28.     int n = va_arg(f->args, int);
  29.     switch (n) {
  30.     case rCreate:        name = ">";    break;
  31.     case rAppend:        name = ">>";    break;
  32.     case rFrom:        name = "<";    break;
  33.     case rHeredoc:        name = "<<";    break;
  34.     case rHerestring:    name = "<<<";    break;
  35.     }
  36.     fmtcat(f, name);
  37.     return FALSE;
  38. }
  39.  
  40. /* defaultfd -- return the default fd for a given redirection operation */
  41.  
  42. extern int defaultfd(int op) {
  43.     return (op == rCreate || op == rAppend) ? 1 : 0;
  44. }
  45.  
  46. /* convert a function in Node * form into something rc can parse (and humans can read?) */
  47.  
  48. static bool Tconv(Format *f, int ignore) {
  49.     Node *n = va_arg(f->args, Node *);
  50.     if (n == NULL) {
  51.         fmtprint(f, "()");
  52.         return FALSE;
  53.     }
  54.     switch (n->type) {
  55.     case nWord:    fmtprint(f, "%S", n->u[0].s);                break;
  56.     case nQword:    fmtprint(f, "%#S", n->u[0].s);                break;
  57.     case nBang:    fmtprint(f, "!%T", n->u[0].p);                break;
  58.     case nCase:    fmtprint(f, "case %T", n->u[0].p);            break;
  59.     case nNowait:    fmtprint(f, "%T&", n->u[0].p);                break;
  60.     case nRmfn:    fmtprint(f, "fn %T", n->u[0].p);            break;
  61.     case nSubshell:    fmtprint(f, "@ %T", n->u[0].p);                break;
  62.     case nAndalso:    fmtprint(f, "%T&&%T", n->u[0].p, n->u[1].p);        break;
  63.     case nAssign:    fmtprint(f, "%T=%T", n->u[0].p, n->u[1].p);        break;
  64.     case nConcat:    fmtprint(f, "%T^%T", n->u[0].p, n->u[1].p);        break;
  65.     case nElse:    fmtprint(f, "{%T}else %T", n->u[0].p, n->u[1].p);    break;
  66.     case nNewfn:    fmtprint(f, "fn %T {%T}", n->u[0].p, n->u[1].p);    break;
  67.     case nIf:    fmtprint(f, "if(%T)%T", n->u[0].p, n->u[1].p);        break;
  68.     case nOrelse:    fmtprint(f, "%T||%T", n->u[0].p, n->u[1].p);        break;
  69.     case nArgs:    fmtprint(f, "%T %T", n->u[0].p, n->u[1].p);        break;
  70.     case nSwitch:    fmtprint(f, "switch(%T){%T}", n->u[0].p, n->u[1].p);    break;
  71.     case nMatch:    fmtprint(f, "~ %T %T", n->u[0].p, n->u[1].p);        break;
  72.     case nWhile:    fmtprint(f, "while(%T)%T", n->u[0].p, n->u[1].p);    break;
  73.     case nLappend:    fmtprint(f, "(%T %T)", n->u[0].p, n->u[1].p);        break;
  74.     case nForin:    fmtprint(f, "for(%T in %T)%T", n->u[0].p, n->u[1].p, n->u[2].p); break;
  75.     case nVarsub:    fmtprint(f, "$%T(%T)", n->u[0].p, n->u[1].p);        break;
  76.     case nCount: case nFlat: case nVar: {
  77.         char *lp = "", *rp = "";
  78.         Node *n0 = n->u[0].p;
  79.  
  80.         if (n0->type != nWord && n0->type != nQword)
  81.             lp = "(", rp = ")";
  82.  
  83.         switch (n->type) {
  84.         default:    panic("this can't happen");        break;
  85.         case nCount:    fmtprint(f, "$#%s%T%s", lp, n0, rp);    break;
  86.         case nFlat:    fmtprint(f, "$^%s%T%s", lp, n0, rp);    break;
  87.         case nVar:    fmtprint(f, "$%s%T%s", lp, n0, rp);    break;
  88.         }
  89.         break;
  90.     }
  91.     case nDup:
  92.         if (n->u[2].i != -1)
  93.             fmtprint(f, "%D[%d=%d]", n->u[0].i, n->u[1].i, n->u[2].i);
  94.         else
  95.             fmtprint(f, "%D[%d=]", n->u[0].i, n->u[1].i);
  96.         break;
  97.     case nBackq: {
  98.         Node *n0 = n->u[0].p, *n00;
  99.         if (n0 != NULL && n0->type == nVar
  100.             && (n00 = n0->u[0].p) != NULL && n00->type == nWord && streq(n00->u[0].s, "ifs"))
  101.             fmtprint(f, "`");
  102.         else
  103.             fmtprint(f, "``%T", n0);
  104.         fmtprint(f, "{%T}", n->u[1].p);
  105.         break;
  106.     }
  107.     case nCbody:
  108.     case nBody: {
  109.         Node *n0 = n->u[0].p;
  110.         if (n0 != NULL)
  111.             fmtprint(f, "%T", n->u[0].p);
  112.         if (n->u[1].p != NULL) {
  113.             if (n0 != NULL && n0->type != nNowait)
  114.                 fmtprint(f, ";");
  115.             fmtprint(f, "%T", n->u[1].p);
  116.         }
  117.         break;
  118.     }
  119.     case nBrace:
  120.         fmtprint(f, "{%T}", n->u[0].p);
  121.         if (n->u[1].p != NULL)
  122.             fmtprint(f, "%T", n->u[1].p);
  123.         break;
  124.     case nEpilog:
  125.     case nPre:
  126.         fmtprint(f, "%T", n->u[0].p);
  127.         if (n->u[1].p != NULL)
  128.             fmtprint(f, " %T", n->u[1].p);
  129.         break;
  130.     case nPipe: {
  131.         int ofd = n->u[0].i, ifd = n->u[1].i;
  132.         fmtprint(f, "%T|", n->u[2].p);
  133.         if (ifd != 0)
  134.             fmtprint(f, "[%d=%d]", ofd, ifd);
  135.         else if (ofd != 1)
  136.             fmtprint(f, "[%d]", ofd);
  137.         fmtprint(f, "%T", n->u[3].p);
  138.         break;
  139.     }
  140.     case nRedir: {
  141.         int op = n->u[0].i;
  142.         fmtprint(f, "%D", op);
  143.         if (n->u[1].i != defaultfd(op))
  144.             fmtprint(f, "[%d]", n->u[1].i);
  145.         fmtprint(f, "%T", n->u[2].p);
  146.         break;
  147.     }
  148.     case nNmpipe: {
  149.         int op = n->u[0].i;
  150.         fmtprint(f, "%D", op);
  151.         if (n->u[1].i != defaultfd(op))
  152.             fmtprint(f, "[%d]", n->u[1].i);
  153.         fmtprint(f, "{%T}", n->u[2].p);
  154.         break;
  155.     }
  156.      }
  157.     return FALSE;
  158. }
  159.  
  160. /* convert a List to an array, for execve() */
  161.  
  162. extern char **list2array(List *s, bool print) {
  163.     char **argv, **av;
  164.  
  165.     if (print)
  166.         fprint(2, "%L\n", s, " ");
  167.     /*
  168.        Allocate 3 extra spots (2 for the fake execve & 1 for defaulting to
  169.        sh) and hide these from exec().
  170.     */
  171.     argv = av = (char **) nalloc((listnel(s) + 4) * sizeof *av) + 3;
  172.     while (s != NULL) {
  173.         *av++ = s->w;
  174.         s = s->n;
  175.     }
  176.     *av = NULL;
  177.     return argv;
  178. }
  179.  
  180. /* figure out the name of a variable given an environment string. */
  181.  
  182. extern char *get_name(char *s) {
  183.     char *eq = strchr(s, '=');
  184.     char *r, *result;
  185.     int c;
  186.     
  187.     if (eq == NULL)
  188.         return NULL;
  189.     r = result = nalloc(eq - s + 1);
  190.     while (1)
  191.         switch (c = *s++) {
  192.         case '=':
  193.             *r++ = '\0';
  194.             return result;
  195. #ifdef PROTECT_ENV
  196.         case '_':
  197.             if (*s == '_') {
  198.                 static const char hexchar[] = "0123456789abcdef";
  199.                 char *h1 = strchr(hexchar, s[1]);
  200.                 char *h2 = strchr(hexchar, s[2]);
  201.                 if (h1 != NULL && h2 != NULL) {
  202.                     *r++ = ((h1 - hexchar) << 4) | (h2 - hexchar);
  203.                     s += 3;
  204.                     break;
  205.                 }
  206.             }
  207.             /* FALLTHROUGH */
  208. #endif
  209.         default:
  210.             *r++ = c;
  211.             break;
  212.         }
  213. }
  214.  
  215. /*
  216.    Hacky routine to split a ^A-separated environment variable. Scans
  217.    backwards. Be VERY CAREFUL with the loop boundary conditions. e.g.,
  218.    notice what happens when there is no ^A in the extdef. (It does
  219.    the right thing, of course :-)
  220. */
  221.  
  222. #define skipleft(p) do --p; while (*p != '\0' && *p != '\001');
  223.  
  224. extern List *parse_var(char *name, char *extdef) {
  225.     char *endp, *realend, *sepp;
  226.     List *tailp, *new;
  227.  
  228.     extdef = strchr(extdef, '=');
  229.     *extdef++ = '\0'; /* null "initiate" the string for rtol scanning */
  230.  
  231.     sepp = realend = strchr(extdef, '\0');
  232.     tailp = NULL;
  233.  
  234.     while (1) {
  235.         endp = sepp;    /* set endp to end of current mebmer */
  236.         skipleft(sepp);    /* advance sepp to the previous \1,  */
  237.         *endp = '\0';   /* and null terminate the member.    */
  238.  
  239.         new = enew(List);
  240.         new->w = ecpy(sepp+1);
  241.         new->m = NULL;
  242.         new->n = tailp;
  243.         tailp = new;
  244.  
  245.         if (sepp < extdef)    /* break when sepp hits the null "initiator" */
  246.             break;
  247.         if (endp != realend)    /* else restore the \1 in between members */
  248.             *endp = '\001';
  249.     }
  250.     if (endp != realend)
  251.         *endp = '\001';
  252.     *--extdef = '='; /* restore extdef '=' */
  253.     return tailp;
  254. }
  255.  
  256. /* get an environment entry for a function and have rc parse it. */
  257.  
  258. #define PREFIX "fn x"
  259. #define PRELEN conststrlen(PREFIX)
  260. extern Node *parse_fn(char *name, char *extdef) {
  261.     Node *def;
  262.     char *s, old[PRELEN];
  263.     if ((s = strchr(extdef, '=')) == NULL)
  264.         return NULL;
  265.     memcpy(old, s -= (PRELEN-1), PRELEN);
  266.     memcpy(s, PREFIX, PRELEN);
  267.     def = parseline(s);
  268.     memcpy(s, old, PRELEN);
  269.     return (def == NULL || def->type != nNewfn) ? NULL : def->u[1].p;
  270. }
  271.  
  272. static bool Aconv(Format *f, int c) {
  273.     char **a = va_arg(f->args, char **);
  274.     if (*a != NULL) {
  275.         fmtcat(f, *a);
  276.         while (*++a != NULL)
  277.             fmtprint(f, " %s", *a);
  278.     }
  279.     return FALSE;
  280. }
  281.  
  282. static bool Lconv(Format *f, int c) {
  283.     List *l = va_arg(f->args, List *);
  284.     char *sep = va_arg(f->args, char *);
  285.     char *fmt = (f->flags & FMT_leftside) ? "%s%s" : "%-S%s";
  286.     if (l == NULL && (f->flags & FMT_leftside) == 0)
  287.         fmtprint(f, "()");
  288.     else {
  289.         List *s;
  290.         for (s = l; s != NULL; s = s->n)
  291.             fmtprint(f, fmt, s->w, s->n == NULL ? "" : sep);
  292.     }
  293.     return FALSE;
  294. }
  295.  
  296. #define    ISMETA(c)    (c == '*' || c == '?' || c == '[')
  297.  
  298. static bool Sconv(Format *f, int ignore) {
  299.     int c;
  300.     unsigned char *s = va_arg(f->args, unsigned char *), *t = s;
  301.     bool quoted    = (f->flags & FMT_altform)  != 0;    /* '#' */
  302.     bool metaquote = (f->flags & FMT_leftside) != 0;    /* '-' */
  303.     if (*s == '\0') {
  304.         fmtprint(f, "''");
  305.         return FALSE;
  306.     }
  307.     if (!quoted) {
  308.         while ((c = *t++) != '\0')
  309.             if (nw[c] == 1 || (metaquote && ISMETA(c)))
  310.                 goto quoteit;
  311.         fmtprint(f, "%s", s);
  312.         return FALSE;
  313.     }
  314. quoteit:
  315.     fmtputc(f, '\'');
  316.     while ((c = *s++) != '\0') {
  317.         fmtputc(f, c);
  318.         if (c == '\'')
  319.             fmtputc(f, '\'');
  320.  
  321.     }
  322.     fmtputc(f, '\'');
  323.     return FALSE;
  324. }
  325.  
  326. void initprint(void) {
  327.     fmtinstall('A', Aconv);
  328.     fmtinstall('L', Lconv);
  329.     fmtinstall('S', Sconv);
  330.     fmtinstall('T', Tconv);
  331.     fmtinstall('D', Dconv);
  332. #ifdef PROTECT_ENV
  333.     fmtinstall('F', Fconv);
  334. #else
  335.     fmtinstall('F', fmtinstall('s', NULL));
  336. #endif
  337. }
  338.